#!/bin/bash
# * =====================================================
# * Copyright © hk. 2022-2025. All rights reserved.
# * File name  : git-ssh.sh
# * Author     : 苏木
# * Date       : 2025-10-19
# * Version    : 
# * Description: 
# * ======================================================
##

# 脚本和工程路径
# ========================================================
SCRIPT_NAME=${0#*/}
SCRIPT_CURRENT_PATH=${0%/*}
SCRIPT_ABSOLUTE_PATH=`cd $(dirname ${0}); pwd`
PROJECT_ROOT=${SCRIPT_ABSOLUTE_PATH}/.. # 工程的源码目录，一定要和编译脚本是同一个目录

source "$PROJECT_ROOT/common/common.sh"

# ========================================================
# 功能实现
# ========================================================
EXECUTE_MODE=manu
function usage()
{
    prt "================================================="
    prt "${PINK}./${SCRIPT_NAME}      : 根据菜单选择功能${CLS}"
    prt "${PINK}./${SCRIPT_NAME} -h   : 显示打印信息用法后显示菜单${CLS}"
    prt "${PINK}./${SCRIPT_NAME} -a   : 自动执行所有步骤${CLS}"
    prt "================================================="
}
# 脚本运行参数处理
notice "There are $# parameters: $@ (\$1~\$$#)"
while getopts "ahp:" arg #选项后面的冒号表示该选项需要参数
    do
        case ${arg} in
            a) EXECUTE_MODE="auto" ;;
            h)
                log_echo_demo
                ;;
            p)
                if [ $OPTARG == "1" ];then
                    message "OPTARG=$OPTARG"
                fi
                ;;
            ?)  #当有不认识的选项的时候arg为?
                error "unkonw argument..."
                exit 1
                ;;
        esac
    done

# 功能函数实现
# ========================================================
# 全局配置
SSH_KEY_TYPE="ed25519"
SSH_KEY_PATH="$HOME/.ssh/id_${SSH_KEY_TYPE}"

# 检测并安装Git
function install_git() 
{
    info "正在检测Git安装..."
    if command -v git &> /dev/null; then
        success "Git已安装, 版本: $(git --version)"
        return 0
    fi

    warning "Git未安装,开始安装..."
    sudo apt update && sudo apt install git -y || {
        error "Git安装失败"
        return 1
    }
    
    success "Git安装成功, 版本: $(git --version)"
}

# 配置Git参数
function configure_git() 
{
    info "开始配置Git参数..."
    
    local username
    local email
    local editor

    # read -p "请输入Git用户名: " username
    # read -p "请输入Git邮箱: " email
    # read -p "请输入默认编辑器 (默认vim): " editor
    username=${username:-sumu}
    email=${email:-2038035593@qq.com}
    editor=${editor:-vim}

    git config --global user.name "$username"
    git config --global user.email "$email"
    git config --global core.editor "$editor"
    git config --global core.autocrlf false
    if command -v vim &> /dev/null; then
        git config --global core.editor vim # 需要提前安装好vim
    else
        git config --global core.editor vi # 一般都还是有vi的
    fi
    git config --global alias.mylog "log --graph --pretty=format:'%C(magenta)[%an]%C(reset) %C(red)%h%C(reset) : %C(green)%s%C(reset) %C(yellow)%d%C(reset) %C(blue)(%cd)%C(reset) ' --abbrev-commit --date=format:'%Y-%m-%d %H:%M:%S'"
    success "Git配置完成,当前配置:"
    git config --global --list | grep -E 'user.name|user.email|core.editor|alias.mylog'
}

function git_completions()
{
    if [ -f /usr/share/bash-completion/completions/git ]; then
        source /usr/share/bash-completion/completions/git
        # 添加到启动脚本中
        # 检查是否已存在目标语句
        local TARGET_LINE="source /usr/share/bash-completion/completions/git"
        local BASHRC_FILE="$HOME/.bashrc"
        if grep -Fxq "$TARGET_LINE" "$BASHRC_FILE"; then
            warning "配置已存在于 $BASHRC_FILE 中"
        else
            # 追加语句到文件末尾并添加换行
            echo -e "\n$TARGET_LINE" >> "$BASHRC_FILE"
            success "已成功添加Git补全配置到.bashrc"
            
            # 可选：立即生效（移除下面两行注释即可启用）
            # source "$BASHRC_FILE"
            # echo "提示：当前会话配置已刷新"
        fi
    else
        # 若是不存在，则下载官方的补全脚本文件
        wget -O ~/.git-completion.bash https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
        echo "source ~/.git-completion.bash" >> ~/.bashrc
        source ~/.bashrc
    fi

}
function usage_vscode_ssh()
{
    prt "通过vscode的 Remote - SSH 插件连接ubuntu大概流程:"
    prt "\t1. 确保windows主机可以ping通ubuntu"
    prt "\t2. 在vscode中执行 ssh $USER@<ip> -a"
    prt "注意:若是可以ping通,但是无法连接,可以尝试删除windows下 C:\Users\username\.ssh\known_hosts 中和ubuntu的ip相关的行,然后重试..."
}
# 检测并安装SSH组件
function install_ssh() 
{
    info "正在检测SSH组件..."
    local missing_packages=()

    # 检测openssh-client
    if ! dpkg -L openssh-client &> /dev/null; then
        missing_packages+=(openssh-client)
    fi

    # 检测openssh-server
    if ! dpkg -L openssh-server &> /dev/null; then
        missing_packages+=(openssh-server)
    fi

    if [ ${#missing_packages[@]} -eq 0 ]; then
        success "SSH组件已安装"
        return 0
    fi

    warning "正在安装缺失的包: ${missing_packages[*]}..."
    sudo apt update && sudo apt install -y "${missing_packages[@]}" || {
        error "SSH组件安装失败"
        return 1
    }
    sudo /etc/init.d/ssh start
    success "SSH组件安装完成"
}

# 测试SSH连接
test_ssh_connection() 
{
    local host=$1
    info "正在测试到 ${host} 的连接..."
    
    # 带超时和主机密钥处理的SSH命令
    if ssh -o ConnectTimeout=10 \
           -o StrictHostKeyChecking=accept-new \
           -T git@${host} 2>&1 | grep -q "successfully authenticated"; then
        success "${host} 连接成功"
        return 0
    else
        local exit_code=${PIPESTATUS[0]}
        case $exit_code in
            0)  warning "${host} 连接异常（服务端返回成功但无权限）" ;;
            255) error "${host} 连接失败(SSH协议错误)" ;;
            *)  error "${host} 连接失败(错误码：${exit_code})" ;;
        esac
        return 1
    fi
}

# 生成SSH密钥
function generate_ssh_key() 
{
    local email=${1:-$USER@$(hostname)}

    warning "正在生成${SSH_KEY_TYPE}类型密钥..."
    ssh-keygen -t ${SSH_KEY_TYPE} -C "$email" -f "${SSH_KEY_PATH}" -N "" || {
        error "密钥生成失败"
        return 1
    }

    success "密钥生成成功，公钥内容:"
    cat "${SSH_KEY_PATH}.pub"
}

# 配置SSH连接
function configure_ssh() 
{
    info "开始配置SSH连接..."
    local email=$(git config --global user.email)
    email=${email:-$USER@$(hostname)}

    # 测试现有连接
    local github_success=0
    local gitee_success=0

    test_ssh_connection "github.com" && github_success=1
    test_ssh_connection "gitee.com" && gitee_success=1

    if [ $github_success -eq 1 ] && [ $gitee_success -eq 1 ]; then
        success "SSH连接配置正常"
        return 0
    fi

    # 生成新密钥
    if [ ! -f "${SSH_KEY_PATH}" ]; then
        generate_ssh_key "$email"
    else
        warning "发现现有SSH密钥: ${SSH_KEY_PATH}"
    fi

    info "请执行以下操作:"
    prt "\t1. 登录代码托管平台"
    prt "\t2. 打开SSH密钥设置页面:"
    prt "\t   - GitHub:  https://github.com/settings/keys"
    prt "\t   - Gitee:   https://gitee.com/profile/sshkeys"
    prt "\t3. 粘贴以下公钥内容:"
    cat "${SSH_KEY_PATH}.pub"
    read -p "按回车键继续测试连接..."

    # 重新测试
    github_success=0
    gitee_success=0
    test_ssh_connection "github.com" && github_success=1
    test_ssh_connection "gitee.com" && gitee_success=1

    if [ $github_success -eq 1 ] && [ $gitee_success -eq 1 ]; then
        success "SSH连接配置正常"
        return 0
    else
        warning "可能存在异常,请重新执行脚本"
    fi
}
# 自动执行所有步骤
function auto_setup() 
{
    install_git && {
        configure_git
        install_ssh
        usage_vscode_ssh
        configure_ssh
    }
    success "所有配置步骤执行完成!"
}

# 菜单与主进程
# ========================================================
function show_menu()
{
    message "================================================="
    message "                script by @苏木    ${CLS}"
    message "================================================="
    prt "${PINK}current path         :$(pwd)${CLS}"
    prt "${PINK}PROJECT_ROOT         :${PROJECT_ROOT}${CLS}"
    prt ""
    prt "* [0] 安装/检测Git"
    prt "* [1] 配置Git参数"
    prt "* [2] 安装SSH组件"
    prt "* [3] 配置SSH连接"
    prt "* [4] 完整执行所有步骤"
    prt "* [5] 自动补全配置"
    prt "* [6] 退出"
    echo "================================================="
}

# 主逻辑
function main() 
{
    if [ "$EXECUTE_MODE" = "manu" ]; then
        while true; do
            show_menu
            read -p "请选择操作 (0-6): " choice
            case $choice in
                0) install_git ;;
                1) configure_git ;;
                2) 
                    install_ssh 
                    usage_vscode_ssh
                    ;;
                3) configure_ssh ;;
                4) auto_setup ;;
                5) git_completions;;
                6) exit 0 ;;
                *) error "无效选项" ;;
            esac
            read -p "按回车继续..."
        done
    else
        info "正在自动执行所有配置步骤..."
        auto_setup
    fi
}

# 执行入口
# show_menu # 菜单显示
main "$@" # 主逻辑执行
